// Effect that modifies an actor
//--------------------------------
#ifndef BUFF_H
#define BUFF_H
#include "common.h"
#include "bbasic.h"

class CompoundBuff;

class Buff : public BIOnTick {
public:

    Buff( uint stackCategory = 0, uint stackCount = 0 );
    virtual ~Buff();

    virtual void SetTarget( Behaved* behaved );
    const Behaved* GetTarget() const;
          Behaved* GetTarget();
    uint  GetStackCategory() const;
    uint  GetStackCount() const;

    // Removal - don't delete directly
    virtual void Destroy();
            bool IsDestroyed() const;

    void StartTimer( uint ticks );
    uint GetTimer() const;
    void Tick();

    // If the buff is conferred by a held or equipped item, you can get it
    friend class Item;
    Item* GetItem();
    bool  IsItemBuff() const;

    // Priority - affects the order in which buff override
    // calls are applied
    void SetPriority( int priority );
    static bool PrioritySort( const Buff* less, const Buff* greater );

#define  PRE_ACTOR if (  IsApplyingPostActor() ) return true
#define POST_ACTOR if ( !IsApplyingPostActor() ) return true

protected:

    virtual bool OnTick();
    virtual void OnBuffApply() { }
    virtual void OnBuffExpire() { }
    bool IsApplyingPostActor() const;

private:

    friend class CompoundBuff;
    friend class Behaved;
    virtual void SetSourceItem( Item* item );
    void SetApplyingPostActor( bool post ) const;

    Behaved* _behaved;
    Item* _sourceItem;

    bool _destroy;
    int  _priority;

    int _timer;
    uint _stackCategory;
    uint _stackCount;

    mutable bool _isApplyingPostActor;
    mutable bool _isNotCountedInStack;

};

class CompoundBuff : public Buff {
public:

    CompoundBuff( uint stackCategory = 0, uint stackCount = 0 );
    virtual ~CompoundBuff() { }

    virtual void SetTarget( Behaved* behaved );
    virtual void Destroy();

    void AddBuff( Buff* buff );

private:

    virtual void SetSourceItem( Item* item );
    BuffList _buffs;
    bool     _sourceItem;

};

#endif
